// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <pollux/functions/lib/subscript_util.h>

namespace kumo::pollux::functions {
    namespace {
        /// element_at(array, index) -> array[index]
        /// element_at(map, key) -> array[map_values]
        ///
        /// - allows negative indices for arrays (if index < 0, accesses elements from
        ///    the last to the first).
        /// - actually return elements from last to first on negative indices.
        /// - allows out of bounds accesses for arrays and maps (returns NULL if out of
        ///    bounds).
        /// - index starts at 1 for arrays.
        class ElementAtFunction : public SubscriptImpl<
                    /* allowNegativeIndices */ true,
                    /* nullOnNegativeIndices */ false,
                    /* allowOutOfBound */ true,
                    /* indexStartsAtOne */ true> {
        public:
            explicit ElementAtFunction(bool allowcaching) : SubscriptImpl(allowcaching) {
            }
        };
    } // namespace

    void registerElementAtFunction(
        const std::string &name,
        bool enableCaching = true) {
        exec::registerStatefulVectorFunction(
            name,
            ElementAtFunction::signatures(),
            [enableCaching](
        const std::string &,
        const std::vector<exec::VectorFunctionArg> &inputArgs,
        const pollux::core::QueryConfig &config) {
                static const auto kSubscriptStateLess =
                        std::make_shared<ElementAtFunction>(false);
                if (inputArgs[0].type->is_array()) {
                    return kSubscriptStateLess;
                } else {
                    return std::make_shared<ElementAtFunction>(
                        enableCaching && config.isExpressionEvaluationCacheEnabled());
                }
            });
    }
} // namespace kumo::pollux::functions
